package repeater

import (
	"context"
	"gitee.com/xcy871622040/gameframe/cluster"
	"gitee.com/xcy871622040/gameframe/service/gateway"
	"gitee.com/xcy871622040/gameframe/service/gateway/ws/repeater/pb"
	"gitee.com/xcy871622040/gameframe/service/gateway/ws/rpcxusage"
	"gitee.com/xcy871622040/gameframe/shareing"
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/protocol"
	"github.com/smallnest/rpcx/share"
	"github.com/xcy8712622040/gnetws/net-protocol/websocket"
	"github.com/xcy8712622040/gnetws/serverhandler"
	"strconv"
	"strings"
	"sync/atomic"
)

var NewMessageSeq = func() func() uint64 {
	var seq uint64
	return func() uint64 {
		return atomic.AddUint64(&seq, 1)
	}
}()

type Repeater struct{ pb.Request } // 请求参数

func (r *Repeater) Proc(ctx *serverhandler.Context) interface{} {
	meta := PreMeta(ctx)
	defer WaitReleaseForMeta(meta)

	message := protocol.NewMessage()
	// 设置请求id
	message.SetSeq(NewMessageSeq())

	// 设置消息序列化类型
	switch ctx.Value(websocket.Protocol).(string) {
	case "json":
		message.SetSerializeType(protocol.JSON)
	default:
		message.SetSerializeType(protocol.ProtoBuffer)
	}

	// 设置请求载体
	message.Payload = r.Payload
	// 设置请求的服务
	message.ServicePath = r.Service
	// 设置请求的方法名
	message.ServiceMethod = r.Method

	// 设置请求的元数据
	var xctx context.Context

	matedata := map[string]string{
		gateway.AppId: cluster.App().Runtime.GenerateServerId(),
	}
	meta.Range(func(k, v string) bool { matedata[k] = v; return true })

	// 设置请求元数据
	xctx = context.WithValue(ctx, share.ReqMetaDataKey, matedata)

	// 发送rpc请求
	mate, buf, err := rpcxusage.XClient(r.Service).SendRaw(xctx, message)
	if err != nil {
		if pars, ok := shareing.ParsError(err); ok {
			code, _ := strconv.Atoi(pars.Get("code"))
			return &pb.Response{
				Method:     r.Method,
				Service:    r.Service,
				StatusCode: uint32(code),
				Payload:    []byte(pars.Get("intr")),
			}
		} else {
			return &pb.Response{
				Method:     r.Method,
				Service:    r.Service,
				Payload:    []byte(err.Error()),
				StatusCode: uint32(pb.Stauts_WS_SERVER_ERROR_RPCX_SENDRAW.Number()),
			}
		}
	}

	// 解析返回元数据
	for _, kv := range strings.Split(mate[client.XMeta], "&") {
		element := strings.Split(kv, "=")
		if element[1] == "" {
			meta.Del(element[0])
		} else {
			meta.Set(element[0], element[1]) // 回写元数据
		}
	}

	return &pb.Response{Service: r.Service, Method: r.Method, StatusCode: uint32(pb.Stauts_WS_SUCCEED), Payload: buf}
}
